iT邦幫忙

第 12 屆 iThome 鐵人賽

0
自我挑戰組

30天找回寫程式手感計劃!!!系列 第 36

Day36 - 「登愣登愣,登愣登登登」~ 隱挑戰 Day12 ─ 果然我的青春寫扣喜劇搞錯了。完

  • 分享至 

  • xImage
  •  

重複是學習之母。繼續寫是完賽之母。
https://ithelp.ithome.com.tw/upload/images/20201012/20129873MJX4opV9lx.png

繼續寫是完賽之母XDDDDDDDDDDD
這會不會太符合我現況XDDDDDDDDDDDDDD

但真的不能再打擾鐵人賽的各位大大們了(?),
其實是團員抱怨他們一直收到通知,
(好啦他們沒抱怨,只是跟我提一下 XD)
而且我也不想拖著這個隱挑戰一直結束不了orz
今天做了一些修改,
但我也不想沒整理 code 就把成果趕著寄出去,
(因為 code 真的很亂QQ)
所以今天是我最後一篇隱挑戰文了,
但我對自己承諾這禮拜一定會把它寄出去!

正片開始

本日課題:昨天提到要改的地方進行修正

1. 戰鬥成功&戰鬥失敗合成一個函數,html 元素也合成一個
html 的部份,我將昨天寫成兩個部份:war_fail、war_success 的戰鬥結果顯示,
合成一個 war_result。

<div class="war_result"></div>

CSS也將共同的部份改到 .war_result,
再將戰鬥成功、失敗不同的 CSS 拆開來。

.war_result{
    position: absolute;
    z-index: 2;

    display: none;
    flex-direction: column;
    align-items: center;

    &.war_success{
        left: 300px;
        top: 120px;

        .message{
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
            margin-bottom: 10px;
        }
        .message1{
            width: 546px;
            height: 118px;
            background-image: url("../img/success1.png");
        }
        .message2{
            width: 664px;
            height: 115px;
            background-image: url("../img/success2.png");
        }
    }
    &.war_fail{
        width: 100%;
        height: 100%;
        background-color: rgba(125, 20, 17, 0.5);
        padding-top: 100px;
        .message{
            color: #c2b6a5;
            font-size: 44px;
            font-family: "新細明體";
            text-shadow: 4px 5px 2px #000000; // 文字陰影效果 (X偏移 Y偏移 Blur 顏色)
            margin-bottom: 10px;
            letter-spacing: 5px; // 文字間距
        }
    }
}

JavaScript 的話,主要就是加上 warStatus 的變數,
戰鬥勝利就將值設為 WIN,
戰鬥失敗就將值設為 FAIL,
然後 finishWar 函數再判斷 warStatus 的值,
來載入不同的 BGM 跟 innerHTML。

let warStatus = "ONGOING";
const warResultElement = document.querySelector(".war_result");

function roleActionExecute(){
        ... 前略 ...
        // 如果怪的血量 <= 0,表示怪被消滅了,後續動作不用執行
        if ( roleStatus[2].HealthPoint[0] <=0 ){
            console.log("戰鬥勝利");
            warStatus = "WIN";
            window.removeEventListener("keydown", optionSelect);
            window.removeEventListener("keydown", skillSelect);
            setTimeout(finishWar, 3000); // 延遲3秒才顯示戰鬥成功
        } 
    
}

function bloodClassReset(){
    if ( currentActor < 2 ){
        monsterBloodMinusElement.textContent = "";
        monsterBloodMinusElement.setAttribute("class",originClass);
        currentActor ++;
    } else{
        girlStatusElement.childNodes[0].setAttribute("class",originClass);
        if ( roleStatus[0].HealthPoint[0] <=0 && roleStatus[1].HealthPoint[0] <=0 ){ 
            console.log("角色全滅");
            warStatus = "FAIL";
            setTimeout(finishWar, 1500); // 延遲1.5秒才顯示戰鬥失敗
        } 
        ... 後略 ...
    }
}

function finishWar(){
    let originClass = warResultElement.getAttribute("class");
    switch(warStatus){
        case "WIN": 
            console.log("戰鬥勝利");
            musicElement.pause();
            setTimeout(function(){ 
                musicElement.loop = false;
                musicElement.src = "bgm/victory.mp3";
                musicElement.play();
            }, 500);
            warResultElement.innerHTML = `
            <div class="message message1"></div>
            <div class="message message2"></div>`;
            warResultElement.style = "display:flex";
            warResultElement.setAttribute("class",`${originClass} war_success animate__animated animate__pulse`);
            break;
        case "FAIL": 
            console.log("角色全滅");
            musicElement.pause();
            setTimeout(function(){ 
                musicElement.loop = false;
                musicElement.src = "bgm/fail.mp3";
                musicElement.play();
            }, 500);
            warResultElement.innerHTML = `
            <div class="message message1">
                勝敗乃兵家常事也
            </div>
            <div class="message message2">
                大俠請重新來過吧
            </div>`;
            warResultElement.style = "display:flex";
            warResultElement.setAttribute("class",`${originClass} war_fail`);
            break;
        default:
            console.log("default");
            break;
    }
    // 要將戰鬥選單及角色狀態隱藏
    warMenuElement.style = "display:none";
    roleStatusElement.style = "display:none";
    monsterBloodElement.style = "display:none";
}

2. 攻擊量要隨機
產生x~y中間的隨機數字這邊參考了 2018 鐵人賽大大的文章→ 用Math.random()取得某區間內的隨機亂數
所以新增了一個產生隨機數字的函數:

function getRandom(min,max){
    return Math.floor(Math.random()*(max-min+1))+min;
}

然後在攻擊的法術的地方代入 getRandom 函數來產生隨機的攻擊量:

function roleActionExecute(){
    ... 前略 ....
    if ( currentActor < 2 ){
        let attackQty;
        switch(roleStatus[currentActor].Action.OptionSelection){
            case "attack": // 動作為攻擊
                attackQty = getRandom(roleStatus[currentActor].AttackPower-5,roleStatus[currentActor].AttackPower+5);
                attackQty -= roleStatus[2].DefensePower;
                break;
            case "skill": // 動作為招式
                let skillSelection = roleStatus[currentActor].Action.SkillSelection;
                attackQty = roleStatus[currentActor].Moves[skillSelection].Cost;
                attackQty *= getRandom(roleStatus[currentActor].MagicAttackPower-5,roleStatus[currentActor].MagicAttackPower+5)*0.5;
                attackQty -= roleStatus[2].DefensePower;
                // 法力消耗
                roleStatus[currentActor].MagicPoint[0] -= roleStatus[currentActor].Moves[skillSelection].Cost;
                break;
            ... 後略 ...
        }
        ... 後略 ...
    }
}

還有怪攻擊的地方也改成攻擊量隨機:

else{
    console.log("輪到怪");
    let attackQty = getRandom(roleStatus[currentActor].AttackPower-5,roleStatus[currentActor].AttackPower+5);
    attackQty -= roleStatus[1].DefensePower;
    roleStatus[1].HealthPoint[0] -= attackQty;
    ... 後略 ...
}

讓我們來看看效果吧!

  • 李逍遙攻擊 -23
    https://ithelp.ithome.com.tw/upload/images/20201012/201298735DIsadYwCK.png
  • 趙靈兒攻擊 -11
    https://ithelp.ithome.com.tw/upload/images/20201012/20129873wfy481kJHk.png
  • 怪攻擊 -26
    https://ithelp.ithome.com.tw/upload/images/20201012/20129873bkoSirpa6s.png
  • 戰鬥成功
    https://ithelp.ithome.com.tw/upload/images/20201012/201298733IqFHWc2Ap.png

隱挑戰打完收工!
ヽ(✿゚▽゚)ノ




隱挑戰暨鐵人賽完結心得(其實這才是本日正文?)

這次是真的要結束這 36 天的鐵人賽了,
其實去年就有寫這個隱挑戰,
去年都硬寫,因此 code 很多地方重複性很高,
今年有解決重複性很高的問題,
比起來今年真的進步了,覺得滿意!

當然還有很多地方可以改的,
例如:怪要隨機攻擊李逍遙或趙靈兒、
(今天原本打算改的,但發現除了隨機選擇對象後,還要其對應的角色狀態再進行扣血,
最麻煩的是要找到該對應的 html 元素再加上動畫,
有點麻煩,就沒改了orz)
兩個角色如果有一個角色血量歸 0,則應該要反灰不能進行攻擊、
法力若小於招式消耗法力不能選擇......等等,
其實有很多眉角可以精進orz

然後深深感覺到寫遊戲真的不容易XD
(我知道我寫的只是很雞毛蒜皮的一小部份而已orz)

鐵人賽結束後,
問我有沒有維持寫程式手感的計劃?
有哦!
這幾天開始在研究 Next.js
然後發現 Next.js 是採用 React 的框架,
React 又牽扯到 JSX 的寫法,
發現小的突然多了好多要學的東西啊!!!!!!
https://www.moedict.tw/%E5%AD%B8%E6%B5%B7%E7%84%A1%E6%B6%AF%E5%8B%A4%E6%98%AF%E5%B2%B8.png
是的,學海無涯,
小的要從這個坑跳往另一片海了XD
也許明年的鐵人賽我就可以寫 30 天學會 Next.js 的題目也說不定呢XD

有些感言其實第 30 天的文章寫過了,
但這邊還是寫一下,
感謝團長之前的揪團,
雖然看到你第 30 天的文章才發現原來你中間也都想放棄XD
只是礙於我跟另外一位團員是自我挑戰仔,
所以你才想說好吧不要放棄(?)

感謝團員一起度過這 30 天,
如果沒有看到你們如此勤勉在拼鐵人賽文章,
小的應該中途可能就會放棄了吧orz

感謝曾經不小心誤入這個系列文的大大們,
還有感謝現在還在拼鐵人賽的大大們,
我脫出了你們加油啊XD(被巴)

最後,感謝我自己,
謝謝你 36 天前挑了這個題目,
雖然中途很多次都很想巴 36 天前的自己,
但是我撐過來了!
而且 36 天以後我寫程式的手感真的從 0 分變成了 60 分!!!!!
也因為這樣才有機會去研究 Next.js,
雖然現在還是處於霧煞煞的狀態,
期望之後的我就可以變得上手了!

那麼,
這一次是認真要跟大家說再見了,
30天找回寫程式手感計劃!!! 本系列文章到此告一段落,
感謝各位的愛戴(?),
各位 2021 見!!!!!
https://ithelp.ithome.com.tw/upload/images/20201012/20129873Gp9v8Wf3PE.png
希望明年真的還有機會再來參加鐵人賽:)

[捨不得說再見(?)的後記]

然後這個系列文是真的有產出複習寫程式手感程序的!
我在第 30 天的文章有寫到,
有興趣的可以右轉至此→ Day30 - 「登愣登愣,登愣登登登」~ 隱挑戰 Day6 暨鐵人賽完賽心得
雖然不希望現在寫程式手感不見,
但萬一有一天又不見的話,
希望自己可以再次參考這次系列文產出的 SOP,
再找回一次手感:D


上一篇
Day35 - 「登愣登愣,登愣登登登」~ 隱挑戰 Day11
系列文
30天找回寫程式手感計劃!!!36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言